import * as PIXI from 'pixi.js';
import { GameConfig, defaultConfig } from './config';
import { Player } from './entities/player';
import { VehicleManager } from './managers/vehicleManager';
import { UI } from './ui/ui';

export class Game {
    private app: PIXI.Application;
    private config: GameConfig;
    private gameContainer: PIXI.Container;
    private player: Player;
    private vehicleManager: VehicleManager;
    private ui: UI;
    private isGameStarted: boolean = false;
    private gameTime: number = 0;
    private currentSpeed: number;
    private isMobile: boolean;
    private gyroscopeAvailable: boolean = false;
    private keyPressed: { [key: string]: boolean } = {};

    constructor(app: PIXI.Application, config: GameConfig = defaultConfig) {
        this.app = app;
        this.config = config;
        this.currentSpeed = config.speed.initial;
        
        // 检测是否为移动设备
        this.isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
        
        // 创建游戏容器
        this.gameContainer = new PIXI.Container();
        this.app.stage.addChild(this.gameContainer);
        
        // 创建背景（分层）
        const { roadLayer, bridgeLayer } = this.createBackground();
        
        // 初始化游戏组件
        this.player = new Player(this.config);
        this.vehicleManager = new VehicleManager(this.config);
        this.ui = new UI(this.config);
        
        // 按照层次添加组件
        this.gameContainer.addChild(roadLayer);          // 底层：马路
        this.gameContainer.addChild(this.vehicleManager.container);  // 中层：车辆
        this.gameContainer.addChild(bridgeLayer);        // 上层：天桥
        this.gameContainer.addChild(this.player.container);  // 最上层：玩家
        this.app.stage.addChild(this.ui.container);
        
        // 设置事件监听
        this.setupEventListeners();
    }

    private setupEventListeners(): void {
        // 触摸/鼠标事件监听
        this.app.view.addEventListener('pointerdown', this.handlePointerDown.bind(this));
        this.app.view.addEventListener('pointerup', this.handlePointerUp.bind(this));
        
        // 键盘事件监听（PC）
        if (!this.isMobile) {
            window.addEventListener('keydown', this.handleKeyDown.bind(this));
            window.addEventListener('keyup', this.handleKeyUp.bind(this));
        }
        
        // 陀螺仪事件监听（移动设备）
        if (this.isMobile) {
            this.setupGyroscope();
        }
        
        // 设置游戏循环
        this.app.ticker.add(this.gameLoop.bind(this));
    }

    private setupGyroscope(): void {
        // 请求陀螺仪权限
        if (typeof DeviceOrientationEvent !== 'undefined' && 
            typeof (DeviceOrientationEvent as any).requestPermission === 'function') {
            // iOS 13+ 需要请求权限
            (DeviceOrientationEvent as any).requestPermission()
                .then((response: string) => {
                    if (response === 'granted') {
                        window.addEventListener('deviceorientation', this.handleGyroscope.bind(this));
                        this.gyroscopeAvailable = true;
                    }
                })
                .catch(console.error);
        } else {
            // 其他设备直接添加监听
            window.addEventListener('deviceorientation', this.handleGyroscope.bind(this));
            this.gyroscopeAvailable = true;
        }
    }

    private handlePointerDown(event: PointerEvent): void {
        if (!this.isGameStarted) return;
        
        // 如果在移动设备上且陀螺仪可用，则不处理触摸事件
        if (this.isMobile && this.gyroscopeAvailable) return;
        
        const rect = (this.app.view as HTMLCanvasElement).getBoundingClientRect();
        const x = event.clientX - rect.left;
        const normalizedX = x / rect.width;
        
        if (normalizedX < 0.5) {
            this.player.startMoving('left');
        } else {
            this.player.startMoving('right');
        }
    }

    private handlePointerUp(): void {
        if (!this.isGameStarted) return;
        
        // 如果在移动设备上且陀螺仪可用，则不处理触摸事件
        if (this.isMobile && this.gyroscopeAvailable) return;
        
        this.player.stopMoving();
    }

    private handleKeyDown(event: KeyboardEvent): void {
        if (!this.isGameStarted) return;
        
        this.keyPressed[event.key] = true;
        
        // 处理方向键和 A/D 键
        if ((event.key === 'ArrowLeft' || event.key === 'a' || event.key === 'A') && 
            !this.keyPressed['ArrowRight'] && !this.keyPressed['d'] && !this.keyPressed['D']) {
            this.player.startMoving('left');
        }
        if ((event.key === 'ArrowRight' || event.key === 'd' || event.key === 'D') && 
            !this.keyPressed['ArrowLeft'] && !this.keyPressed['a'] && !this.keyPressed['A']) {
            this.player.startMoving('right');
        }
    }

    private handleKeyUp(event: KeyboardEvent): void {
        if (!this.isGameStarted) return;
        
        this.keyPressed[event.key] = false;
        
        // 检查是否还有其他方向键被按下
        if ((event.key === 'ArrowLeft' || event.key === 'a' || event.key === 'A') && 
            (this.keyPressed['ArrowRight'] || this.keyPressed['d'] || this.keyPressed['D'])) {
            this.player.startMoving('right');
        } else if ((event.key === 'ArrowRight' || event.key === 'd' || event.key === 'D') && 
            (this.keyPressed['ArrowLeft'] || this.keyPressed['a'] || this.keyPressed['A'])) {
            this.player.startMoving('left');
        } else {
            this.player.stopMoving();
        }
    }

    private handleGyroscope(event: DeviceOrientationEvent): void {
        if (!this.isGameStarted || !event.gamma) return;
        
        // gamma 值范围为 -90 到 90，表示左右倾斜
        const tiltThreshold = 10;  // 倾斜阈值
        const gamma = event.gamma;
        
        if (gamma < -tiltThreshold) {
            this.player.startMoving('left');
        } else if (gamma > tiltThreshold) {
            this.player.startMoving('right');
        } else {
            this.player.stopMoving();
        }
    }

    private gameLoop(delta: number): void {
        if (!this.isGameStarted) return;
        
        // 更新游戏时间
        this.gameTime += this.app.ticker.elapsedMS;
        
        // 更新速度
        this.updateSpeed();
        
        // 更新游戏组件
        this.player.update(delta);
        this.vehicleManager.update(delta, this.currentSpeed);
        
        // 更新影子碰撞区域（仅用于碰撞检测，不显示）
        this.player.updateCollisionBox();
        
        // 检测碰撞
        if (this.checkCollisions()) {
            this.handleGameOver();
        }
        
        // 更新UI
        this.ui.updateTimer(this.gameTime);
    }

    private updateSpeed(): void {
        // 基础速度增长
        const speedIncreaseTimes = Math.floor(this.gameTime / this.config.speed.increaseInterval);
        const baseSpeed = this.config.speed.initial * 
            Math.pow(1 + this.config.speed.increaseRate, speedIncreaseTimes);
        
        // 添加波动效果（在基础速度的90%到110%之间波动）
        const fluctuation = 0.2; // 波动范围为±10%
        const wave = Math.sin(this.gameTime / 1000) * fluctuation;
        const speedWithWave = baseSpeed * (1 + wave * 0.1);
        
        // 确保速度不超过最大限制
        this.currentSpeed = Math.min(speedWithWave, this.config.speed.max);
    }

    private checkCollisions(): boolean {
        const result = this.vehicleManager.checkCollisionWithShadow(this.player.getShadowPolygon());
        if (result.collided && result.point) {
            this.player.showCollisionEffect(result.point);
        }
        return result.collided;
    }

    private handleGameOver(): void {
        this.isGameStarted = false;
        // 延迟显示游戏结束界面，让玩家能看到碰撞效果
        setTimeout(() => {
            this.ui.showGameOver(this.gameTime, () => this.restart());
        }, 1000);
    }

    public start(): void {
        this.ui.showCountdown(() => {
            this.isGameStarted = true;
            this.gameTime = 0;
            this.currentSpeed = this.config.speed.initial;
            this.vehicleManager.start();
        });
    }

    public restart(): void {
        // 重置游戏状态
        this.player.reset();
        this.vehicleManager.reset();
        this.start();
    }

    private createBackground(): { roadLayer: PIXI.Container, bridgeLayer: PIXI.Container } {
        const roadLayer = new PIXI.Container();
        const bridgeLayer = new PIXI.Container();
        
        // 1. 绘制马路层
        const road = new PIXI.Graphics();
        
        // 路面底色（浅灰色，让影子更容易看见）
        road.beginFill(0x95a5a6);  // 浅灰色
        road.drawRect(0, 0, this.config.screenWidth, this.config.screenHeight);  // 延伸到整个屏幕
        road.endFill();

        // 添加路面纹理（柏油路面效果）
        const addRoadTexture = () => {
            road.lineStyle(0);
            for (let i = 0; i < 1000; i++) {  // 增加纹理密度以覆盖更大区域
                const x = Math.random() * this.config.screenWidth;
                const y = Math.random() * this.config.screenHeight;
                const size = Math.random() * 2 + 1;
                const alpha = Math.random() * 0.05;  // 降低纹理对比度
                
                road.beginFill(0x7f8c8d, alpha);  // 使用中灰色
                road.drawCircle(x, y, size);
                road.endFill();
            }
        };

        // 应用路面纹理
        addRoadTexture();

        // 绘制车道分隔线
        const drawLaneLines = () => {
            const laneWidth = this.config.screenWidth / this.config.laneCount;
            for (let i = 1; i < this.config.laneCount; i++) {
                const x = i * laneWidth;
                
                // 上半部分虚线
                for (let y = 10; y < this.config.screenHeight * 0.5; y += 30) {
                    road.lineStyle(2, 0xffffff, 0.3);  // 降低车道线亮度
                    road.moveTo(x, y);
                    road.lineTo(x, y + 15);
                }
                
                // 天桥下方的虚线
                for (let y = this.config.screenHeight * 0.63; y < this.config.screenHeight; y += 30) {
                    road.lineStyle(2, 0xffffff, 0.3);  // 降低车道线亮度
                    road.moveTo(x, y);
                    road.lineTo(x, y + 15);
                }
            }
        };

        // 应用车道线
        drawLaneLines();

        // 添加路面反光效果
        const addRoadShine = () => {
            // 上部反光
            road.lineStyle(0);
            road.beginFill(0xffffff, 0.03);
            road.drawRect(0, 0, this.config.screenWidth, this.config.screenHeight * 0.1);
            road.endFill();

            // 中间部分（天桥前的渐变效果）
            const steps = 10;
            for (let i = 0; i < steps; i++) {
                const alpha = 0.02 - (i * 0.02 / steps);
                road.beginFill(0xffffff, alpha);
                road.drawRect(
                    0,
                    this.config.screenHeight * (0.1 + i * 0.03),
                    this.config.screenWidth,
                    this.config.screenHeight * 0.03
                );
                road.endFill();
            }

            // 天桥下方的反光
            for (let i = 0; i < steps; i++) {
                const alpha = 0.02 - (i * 0.02 / steps);
                road.beginFill(0xffffff, alpha);
                road.drawRect(
                    0,
                    this.config.screenHeight * (0.63 + i * 0.03),
                    this.config.screenWidth,
                    this.config.screenHeight * 0.03
                );
                road.endFill();
            }
        };

        // 应用路面反光效果
        addRoadShine();

        roadLayer.addChild(road);

        // 2. 绘制天桥层
        const bridge = new PIXI.Graphics();
        
        // 天桥的影子（半透明深色）
        bridge.beginFill(0x2c3e50, 0.3);  // 深色，30%不透明度
        bridge.lineStyle(0);
        
        // 桥面的影子
        bridge.drawRect(0, this.config.screenHeight * 0.35, 
                       this.config.screenWidth, this.config.screenHeight * 0.05);
        
        // 支柱的影子（略微倾斜）
        const pillarShadowWidth = 15;
        const shadowSkew = 10;  // 影子倾斜度
        
        // 左支柱影子
        bridge.moveTo(this.config.screenWidth * 0.2 - pillarShadowWidth/2 + shadowSkew, this.config.screenHeight * 0.35);
        bridge.lineTo(this.config.screenWidth * 0.2 + pillarShadowWidth/2 + shadowSkew, this.config.screenHeight * 0.35);
        bridge.lineTo(this.config.screenWidth * 0.2 + pillarShadowWidth/2, this.config.screenHeight * 0.5);
        bridge.lineTo(this.config.screenWidth * 0.2 - pillarShadowWidth/2, this.config.screenHeight * 0.5);
        bridge.closePath();
        
        // 右支柱影子
        bridge.moveTo(this.config.screenWidth * 0.8 - pillarShadowWidth/2 + shadowSkew, this.config.screenHeight * 0.35);
        bridge.lineTo(this.config.screenWidth * 0.8 + pillarShadowWidth/2 + shadowSkew, this.config.screenHeight * 0.35);
        bridge.lineTo(this.config.screenWidth * 0.8 + pillarShadowWidth/2, this.config.screenHeight * 0.5);
        bridge.lineTo(this.config.screenWidth * 0.8 - pillarShadowWidth/2, this.config.screenHeight * 0.5);
        bridge.closePath();
        
        bridge.endFill();
        
        // 桥面
        bridge.beginFill(0x7f8c8d);  // 深灰色
        bridge.lineStyle(2, 0x6c7a7a);  // 边框
        bridge.drawRect(0, this.config.screenHeight * 0.55, 
                       this.config.screenWidth, this.config.screenHeight * 0.08);
        bridge.endFill();
        
        // 桥的支柱
        const pillarWidth = 20;
        const pillarHeight = this.config.screenHeight * 0.15;  // 减半高度
        const pillarY = this.config.screenHeight * 0.63;
        
        bridge.beginFill(0x7f8c8d);
        // 左支柱
        bridge.drawRect(this.config.screenWidth * 0.2 - pillarWidth/2, 
                       pillarY, pillarWidth, pillarHeight);
        // 右支柱
        bridge.drawRect(this.config.screenWidth * 0.8 - pillarWidth/2, 
                       pillarY, pillarWidth, pillarHeight);
        bridge.endFill();
        
        // 栏杆
        const railingHeight = 15;
        bridge.beginFill(0x95a5a6);
        bridge.lineStyle(1, 0x6c7a7a);
        
        // 栏杆立柱
        const postSpacing = 30;
        const postWidth = 4;
        for (let x = 0; x < this.config.screenWidth; x += postSpacing) {
            bridge.drawRect(x, this.config.screenHeight * 0.55 - railingHeight,
                          postWidth, railingHeight);
            bridge.drawRect(x, this.config.screenHeight * 0.63 - railingHeight,
                          postWidth, railingHeight);
        }
        
        // 栏杆横杆
        bridge.lineStyle(2, 0x95a5a6);
        bridge.moveTo(0, this.config.screenHeight * 0.55 - railingHeight * 0.7);
        bridge.lineTo(this.config.screenWidth, this.config.screenHeight * 0.55 - railingHeight * 0.7);
        bridge.moveTo(0, this.config.screenHeight * 0.63 - railingHeight * 0.3);
        bridge.lineTo(this.config.screenWidth, this.config.screenHeight * 0.63 - railingHeight * 0.3);
        
        bridgeLayer.addChild(bridge);
        
        return { roadLayer, bridgeLayer };
    }
}